class Caracterizacao < ActiveRecord::Base

  belongs_to :pleito
  validates_presence_of :pleito
  attr_readonly :pleito_id

  delegate :reducao?, :reducao_fixa?, :isencao?, :reinvestimento?,
           :depreciacao?, :isencao_ou_depreciacao?, :to => :pleito

  validates_presence_of :mercado_atuacao, :objetivo

  # Redução
  has_many :atividades, :dependent => :destroy
  has_many :produtos, :through => :atividades

  # Redução Fixa
  validates_inclusion_of :tipo_projeto, :in => TipoProjeto.mnemonics, :if => :reducao_fixa?
  validates_inclusion_of :infra_estrutura, :in => [true, false], :if => :ampliacao_ou_mod_parcial?

  def ampliacao_ou_mod_parcial?
    %w(ampliacao modernizacao_parcial).include? tipo_projeto
  end

  def documentos
    TipoProjeto.documentos(tipo_projeto)
  end

  def ampliacao_minima
    infra_estrutura? ? 20 : 50
  end

  # Isenção e Depreciação
  validates_inclusion_of :tipo_projeto, :in => TipoProjeto.mnemonics(:isencao_ou_depreciacao), :if => :isencao_ou_depreciacao?

  # Isenção
  with_options :if => :isencao? do |i|
    i.validate :ao_menos_uma_isencao_selecionada
    i.validates_inclusion_of :projeto_concluido, :in => [true, false]
  end

  def ao_menos_uma_isencao_selecionada
    return if adicional_frete_renovacao || iof_cambio_importacao
    errors.add_to_base "Ao menos uma das opções deve ser selecionada."
  end

  # Depreciação
  validate :ao_menos_uma_depreciacao_selecionada, :if => :depreciacao?

  def ao_menos_uma_depreciacao_selecionada
    return if depreciacao_acelerada || desconto_pis_pasep_cofins
    errors.add_to_base "Ao menos uma das opções deve ser selecionada."
  end

  # Reinvestimento
  with_options :dependent => :destroy do |c|
    has_many :investimentos do
      def total # C
        sum(:valor)
      end
    end
    has_many :depositos do
      def total # A
        sum('valor + complementacao').to_f
      end

      def totais_parciais
        first :select => 'sum(valor) as valor, sum(complementacao) as complementacao'
      end

      def totais_por_ano
        totais = all :group => 'ano, data', :select => 'ano, sum(valor) as valor, sum(complementacao) as complementacao, sum(valor + complementacao) as total'
        totais.each { |row| row.valor = row.valor.to_f; row.total = row.total.to_f }
      end

      def custo_administracao
        0.02 * total
      end
    end
    has_many :opcoes_dipj do
      def total
        sum(:reducao)
      end

      def complementacao
        total / 2
      end
    end
  end
  has_many :documentos_fiscais, :through => :investimentos, :uniq => true

  def fontes_e_usos # Total Fontes e Usos
    if reinvestimento_parcelado
      (investimentos.total / 0.98) # C / 0.98
    else
      investimentos.total + custo_administracao # C + D
    end
  end

  def depositos_total # A
    round(opcoes_dipj.total * 1.5)
  end

  def previsao_ou_complementacao # B
    round(fontes_e_usos - depositos_total)
  end

  def complementacao # B = C + D - A
    previsao_ou_complementacao
  end

  def previsao # B = C / 0.98 - A
    previsao_ou_complementacao
  end

  def previsao_da_complementacao # b2 = B - b1
    previsao_ou_complementacao - previsao_de_reducao
  end

  def previsao_de_reducao # b1 = 2 x B/ 3
    round(2 * previsao_ou_complementacao / 3)
  end

  def investimentos_total # C
    investimentos.total
  end

  def custo_administracao # D
    if reinvestimento_parcelado
      0.02 * (depositos_total + previsao_ou_complementacao)
    else
      0.02 * depositos_total
    end
  end

  private

  def round(valor)
    BigDecimal.new(valor.to_s).truncate(2).to_f
  end

end
